﻿using System;
using System.Net.Mail;
using System.Diagnostics;
using System.IO;

namespace DotNetNexusSpam.SpamFilter
{
    /// <summary>
    /// This filter allows to use SpamAssassin. 
    /// The version we use is a Windows port avaible but discontinued at http://sawin32.sourceforge.net/
    /// Quick note about the argument provided to SA: 
    /// -e, --exit-code Exit with a non-zero exit code if the tested message was spam
    /// -L, --local Local tests only (no online tests)     
    /// > path_to_email absolute path to email file
    /// </summary>
    class SpamAssassinFilter : FilterBase
    {
        public SpamAssassinFilter(CDOMessageWrapper email, string startupPath)
            : base(email, startupPath)
        {
            base.Name = "SpamAssassin";
        }

        private const string CMD_PATH = @"C:\WINDOWS\System32\cmd.exe";
        public override void Fire()
        {
            Process p = new Process();
            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.UseShellExecute = false;
            // The /C parameter tells CMD to carry out the command (contained in _arguments) and then to terminate.
            p.StartInfo.Arguments = @" /C " + _arguments;
            p.StartInfo.FileName = CMD_PATH;
            // uncomment following line to watch output inside console
            //p.OutputDataReceived += (sender, arguments) => Console.WriteLine("Received output: {0}", arguments.Data);
            try
            {
                p.Start();
                p.BeginOutputReadLine();
                p.WaitForExit();
                int exitCode = 0;
                if (!int.TryParse(p.ExitCode.ToString(), out exitCode))
                    exitCode = 0;
                if (exitCode > 0)
                {
                    _log.Info("SpamAssassin classified email as SPAM.");
                    base.ActionToTake = FilterAction.DELETE_EMAIL;
                    base.IsSpam = true;
                } else
                    _log.Info("SpamAssassin classified email as HAM.");
            }
            catch (Exception excp)
            {
                _log.Error("SpamAssassin could not be executed correclty.", excp);
            }
            finally
            {
                p.Close();
            }
        }

        /// <summary>
        /// Load SpamAssassin's configuration.
        /// </summary>
        private const string SPAM_ASSASSIN = "spamAssassin.txt";
        private string[] _spamConfig;
        private string _spamAssassinPath = "";
        private string _arguments = "";
        public override void LoadConfiguration()
        {
            string settingsPath = base.StartupPath + "config\\" + SPAM_ASSASSIN;
            if (File.Exists(settingsPath))
            {
                string spamConfigContent = "";
                using (StreamReader settingsReader = new StreamReader(settingsPath))
                    spamConfigContent = settingsReader.ReadToEnd();
                _spamConfig = spamConfigContent.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
                _log.Debug("SpamAssassin's configuration was loaded succesfully.");
                if (_spamConfig.Length >= 1)
                {
                    _spamAssassinPath = _spamConfig[0].Trim();
                    _arguments = String.Format(@" {0} < ""{1}""", _spamAssassinPath, base.Email.PathToEmailFile);
                }
            }
            else
            {
                _log.Warn("SpamAssassin file could not be loaded from " + settingsPath);
            }
        }
    }
}
